module main;

import std.stdio;
import std.conv;
import std.exception;
import std.stdint;
import instr;
import std.getopt;

immutable VERSION = "1.0.0";
immutable __id = "$Id$";

string toString(E)(E val) if (is(E == enum))
{
	foreach (s; __traits(allMembers, E))
	{
		if (val == mixin("E."~s)) return s;
	}
	return null;
}

ulong buildInstructionSet16()
{
	instr16["nop"] = Instruction!uint16_t("nop", 16,0,0x0000,0xFFFF);
	instr16["clc"] = Instruction!uint16_t("nop", 16,0,0x0000,0xFFFF);;
	instr16["cli"] = Instruction!uint16_t("cli",16,0,0x94f8, 0xFFFF);
	instr16["clh"] = Instruction!uint16_t("clh",16,0,0x94d8,0xffff);
	instr16["cln"] = Instruction!uint16_t("cln",16,0,0x94a8,0xffff);
	
	return instr16.length;
}
	
int main(string [] args)
{
	string defFilename = "instr.sdl";
	bool bVerbose = false;
	bool bUsage = false, bSummary = false;
	bool bStats = false, bInteractive = false;
	string opcode = "";

	getopt(
		args,
		"instr|i", &defFilename,
		"help|h", &bUsage,
		"verbose|v", &bVerbose,
		"summary", &bSummary,
		"stats", &bStats,
		"shell", &bInteractive,
		"opcode|o", &opcode
		);

	if (bUsage) {
		usage();
		return 0;
	} else if (bSummary)
	{
		printSummary();
		return 0;
	} else if (bStats)
	{
		printStats();
		return 0 ;
	} else if (opcode != "")
	{
		printInstructionInfo(opcode);
		return 0;

	} else if (bInteractive)
	{
		startShell();
		return 0;
	}

	writeln("OperandFlag.size = ", OperandFlag.sizeof);
	writeln("OperandFlag.max = ", cast (ushort)OperandFlag.max);
	writeln("OperandFlag.min = ", cast (ushort)OperandFlag.min);
	
	auto n = buildInstructionSet16();
	
	try
	{
		writeln("[",args[1],"]");
		writeln(n, " instructions loaded.");
		auto i = instr16[args[1]];
		writefln("16bit Instruction: %s Hex: 0x%x Bin: 0b%b", args[1], i.code, i.code);
		writefln("---> Code bitmask: 0x%x Code bits: %d",i.mask,i.bits);
		writefln("---> Operands: %d %s, %s", i.numOperands, "","");
	} 
	catch(core.exception.RangeError e)
	{
		writeln("That opcode was not found.");
	}

	return 0;
}

void startShell()
{

}

void printInstructionInfo(string o)
{

}

void printSummary()
{

}

void printStats()
{

}

void banner()
{
	writeln("AVR Instruction Set To Machine Code");
	writeln("Copyright 2013 Open Design Strategies, LLC");
	writeln("Licensed under OSI-certified CDDL Open Source License");
	writeln("");
}

void usage()
{
	banner();
	writeln("avr-i2m [options]");
	writeln("where [options] is one ore more of the following:");
	writeln("-i, --instr=<filename>            Load instruction set in <filename>");
	writeln("--shell                           Run in interactive mode");
	writeln("-o, --opcode=<opcode>             Target <opcode> instruction");
	writeln("-v, --verbose                     Enable verbose reporting");
	writeln("--summary                         Print summary of instruction set");
	writeln("--stats                           Display instruction set statistics");
	writeln("-h, --help                        Show this help listing");    
}

